package cn.whale.gateway.filter;

import cn.whale.gateway.vo.JSONResult;
import com.alibaba.fastjson.JSON;
import lombok.extern.log4j.Log4j2;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Map;

@Log4j2
@Component
public class KillStoreCheckFilter implements GatewayFilter, Ordered {
    public static final String KEY_KILL_COURSE_SEMAPHORE = "key_kill_course_semaphore:%S";
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //检查库存，是否能秒杀
        if(!canKill(exchange)){
            return getResponse(exchange,JSON.toJSONString(JSONResult.errorMessage("秒杀商品失败，数量不够啦")));
        }
        return chain.filter(exchange);
    }

    //是否能秒杀
    private boolean canKill(ServerWebExchange exchange){
        Object requestBody = exchange.getAttribute("cachedRequestBodyObject");
        if(null != requestBody){
            Map<String,Object> bodyParams = JSON.parseObject(requestBody.toString(), Map.class);
            Object courseId = bodyParams.get("courseId");
            if(courseId == null){
                log.error("无效的课程ID：{}",courseId);
                return false;
            }

            int killCount = 1;
            Object killCountObj = bodyParams.get("killCount");
            if(killCountObj != null){
                killCount = Integer.valueOf(killCountObj.toString());
            }
            //判断库存
            RSemaphore semaphore = redissonClient.getSemaphore(String.format(KEY_KILL_COURSE_SEMAPHORE, courseId.toString()));
            if(semaphore.availablePermits() < killCount){
                log.error("秒杀商品失败，数量不够啦：{}",semaphore.availablePermits());
                return false;
            }
        }
        return true;
    }
    //封装结果
    private Mono<Void> getResponse(ServerWebExchange exchange, String content){
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        DataBuffer dataBuffer = response.bufferFactory().allocateBuffer().write(content.getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Mono.just(dataBuffer));
    }

    @Override
    public int getOrder() {
        return -5;
    }
}